URLを外部リンク記法に変換するUserScript (TamperMonkeyなし)
from
code:mod.ts
import { useStatusBar } from "../scrapbox-userscript-std/dom.ts";
import { getWebPageTitle, getTweetInfo } from "../scrapbox-userscript-std/rest.ts";
import type { TweetInfo } from "../scrapbox-jp%2Ftypes/rest.ts";
const checkRegExp = /(https?:\/\/\S+)/;
export const hasURL = (text: string): boolean => checkRegExp.test(text);
export const convert = async (text: string): Promise<string> => {
if (!hasURL(text)) return text;
const { render, dispose } = useStatusBar();
render(
{ type: "spinner" },
{ type: "text", text: "convert URLs..."},
);
let count = 0;
try {
const result = await Promise.all(
text.split(checkRegExp).map(async (fragment) => {
if (!/^https?:\/\/\S+/.test(fragment)) return fragment;
let url: URL;
try {
url = new URL(fragment);
} catch(e: unknown) {
if (e instanceof TypeError) return fragment;
throw e;
}
if (isTwitterURL(url)) {
const result = await getTweetInfo(url);
if (!result.ok) return fragment;
count++;
return formatTweet(url, result.value);
}
const result = await getWebPageTitle(url);
if (!result.ok) return fragment;
count++;
const title = result.value
.replace(/\s/g, " ") // スペースと改行を全て半角スペースにする
.replaceAll("[", "[")
.replaceAll("]", "]");
return [${url} ${title}];
})
);
render(
{ type: "check-circle" },
{ type: "text", text: Converted ${count} URLs.},
);
return result.join("");
} catch(e: unknown) {
render(
{ type: "exclamation-triangle" },
{ type: "text", text: e instanceof Error ?
${e.name} ${e.message} :
Unknown error! (see developper console),
},
);
console.error(e);
throw e;
} finally {
setTimeout(() => dispose(), 1000);
}
};
Tweetのformat
code:mod.ts
const isTwitterURL = (url: string | URL) =>
/^https:\/\/(?:www\.|mobile\.|m\.|)twitter\.com\/(A-Za-z0-9_*)\/(?:status|statuses)\/\d+/.test(url.toString()); const escapeForEmbed = (text: string) => text
.replace(/\b/gm, "")
.replace(/\s*[\`]\s*/g, " ") .trim();
const formatTweet = (url: URL, tweet: TweetInfo) => [
[${escapeForEmbed(tweet.screenName)}(@${escapeForEmbed(tweet.userName)}) ${url.origin}${url.pathname}],
...tweet.description.split("\n").map((line) => > ${escapeForEmbed(line)}),
...(tweet.images.length > 0 ? [> ${tweet.images.map((image) => ${image})}] : []), ].join("\n");